package com.huangfuyi.process.actuator.threadpool;

import com.huangfuyi.process.actuator.definition.EPConditionParser;
import com.huangfuyi.process.actuator.monitor.EPMonitorThreadManager;
import com.huangfuyi.process.entity.instance.EPInstanceEntity;
import com.huangfuyi.process.entity.mainthread.EPInstance;
import com.huangfuyi.process.entity.model.EPModelEntity;
import com.huangfuyi.process.entity.node.EPNodeEntity;
import com.huangfuyi.process.entity.node.EPNodeNextConfigEntity;
import com.huangfuyi.process.entity.running.EPParamEntity;
import com.huangfuyi.process.entity.running.EPRunningEntity;
import com.huangfuyi.process.exceptions.EPExecutorException;
import com.huangfuyi.process.managers.EPManagers;
import com.huangfuyi.process.managers.EPNodeAppManager;
import com.huangfuyi.process.managers.EPServiceManager;
import com.huangfuyi.process.service.EPCoreInstanceService;
import com.huangfuyi.process.service.EPCoreModelService;
import com.huangfuyi.process.service.EPCoreRunningService;
import com.huangfuyi.process.utils.EPObjectUtils;

import java.util.List;
import java.util.Locale;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.logging.Logger;

public class EPMainThreadPool {

    private static final Logger log = Logger.getLogger("EPMainThreadPool");

    // 核心线程数量
    private static int coreSize = 10;

    // 任务队列大小
    private static int queueSize = 1000;

    // 任务队列
    protected static BlockingQueue<EPInstance> taskQueue;

    // 线程集合
    protected static List<EPMainThread> threads;

    // 线程名称后缀
    private static int threadIndex;

    // 初始化线程池
    public static void init(int coreSize, int queueSize) {
        log.info("核心线程池： 初始化核心线程池······");
        // 核心线程数量级队列大小需要大于0
        if (coreSize > 0) {
            EPMainThreadPool.coreSize = coreSize;
        }

        if (queueSize > 0) {
            EPMainThreadPool.queueSize = queueSize;
        }
        log.info(String.format(Locale.ROOT, "核心线程池： 核心线程数量：%d， 任务队列大小：%d", EPMainThreadPool.coreSize, EPMainThreadPool.queueSize));

        // 终止所有运行中线程， 标记为满线程后，线程将在运行完当前任务后终止
        if (!EPObjectUtils.isEmpty(EPMainThreadPool.threads)) {
            for (EPMainThread thread : EPMainThreadPool.threads) {
                thread.markAsSlow();
            }
        }

        EPMainThreadPool.taskQueue = new LinkedBlockingDeque<>(EPMainThreadPool.queueSize);
        EPMainThreadPool.threads = new CopyOnWriteArrayList<>();
        log.info("核心线程池： 核心线程池初始化完成");
        log.info("核心线程池： 启动监控······");
        EPMonitorThreadManager.init();
        log.info("核心线程池： 启动监控完成！");

    }

    // 使用默认值初始化核心线程池
    public static void init() {
        EPMainThreadPool.init(EPMainThreadPool.coreSize, EPMainThreadPool.queueSize);
    }


    // 提交节点任务到线程池
    public static synchronized void execute(EPInstance instance) {
        if (EPObjectUtils.isEmpty(EPMainThreadPool.taskQueue) || EPObjectUtils.isEmpty(EPMainThreadPool.threads)) {
            EPMainThreadPool.init();
        }

        if (EPMainThreadPool.threads.size() < EPMainThreadPool.coreSize) {
            EPServiceManager<? extends EPInstanceEntity, ? extends EPModelEntity, ? extends EPNodeEntity, ? extends EPNodeNextConfigEntity, ? extends EPRunningEntity, ? extends EPParamEntity> serviceManager = EPManagers.getServiceManager();
            EPCoreRunningService<? extends EPRunningEntity, ? extends EPParamEntity> runningService = serviceManager.getRunningService();
            EPCoreInstanceService<? extends EPInstanceEntity, ? extends EPModelEntity, ? extends EPNodeEntity, ? extends EPNodeNextConfigEntity, ? extends EPRunningEntity, ? extends EPParamEntity> instanceService = serviceManager.getInstanceService();
            EPCoreModelService<? extends EPModelEntity, ? extends EPNodeEntity, ? extends EPNodeNextConfigEntity> modelService = serviceManager.getModelService();
            EPNodeAppManager nodeAppManager = EPManagers.getNodeAppManager();
            EPConditionParser conditionParser = EPManagers.getConditionParser();

            EPMainThread mainThread = new EPMainThread(runningService, nodeAppManager, instanceService, modelService, conditionParser);
            mainThread.setName("EPMainThread-" + (++EPMainThreadPool.threadIndex));
            EPMainThreadPool.threads.add(mainThread);
            mainThread.start();
        }

        boolean offer = EPMainThreadPool.taskQueue.offer(instance);
        if (!offer) {
            throw new EPExecutorException("执行器队列已满！");
        }
    }

    private EPMainThreadPool() {
    }
}
